home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 February: Tool Chest / Apple Developer CD Series Tool Chest February 1996 (Apple Computer)(1996).iso / Tool Chest / Text / WASTE / WASTE 1.1.2 Distribution / Demo Source / WEDemoMenus.p < prev    next >
Encoding:
Text File  |  1995-10-12  |  22.2 KB  |  960 lines  |  [TEXT/CWIE]

  1. unit WEDemoMenus;
  2.  
  3. { WASTE DEMO PROJECT: }
  4. { Menu Handling }
  5.  
  6. { Copyright © 1993-1995 Marco Piovanelli }
  7. { All Rights Reserved }
  8.  
  9. interface
  10.     uses
  11.         WEDemoIntf;
  12.  
  13.     function InitializeMenus: OSErr;
  14.     procedure PrepareMenus;
  15.     procedure DoMenuChoice (menuChoice: LongInt);
  16.     function DoClose (closing: ClosingOption;
  17.                                     saving: SavingOption;
  18.                                     window: WindowRef): OSErr;
  19.     function DoQuit (saving: SavingOption): OSErr;
  20.  
  21. implementation
  22.     uses
  23.         Aliases, Devices, LowMem, StandardFile, ToolUtils, WEDemoAbout, WEDemoFiles, WEDemoWindows, DialogUtils, WETabs;
  24.  
  25.     const
  26.  
  27. { resource types }
  28.  
  29.         kTypeMenuColorTable = 'mctb';
  30.  
  31.     var
  32.  
  33.         sColors: Handle;            { handle to the 'mctb' resource for the Color menu }
  34.         
  35.     procedure SetDefaultDirectory({const} var spec: FSSpec);
  36.     begin
  37.         LMSetCurDirStore(spec.parID);
  38.         LMSetSFSaveDisk(-spec.vRefNum);
  39.     end;  { SetDefaultDirectory }
  40.  
  41.     function MySFDialogFilter (dialog: DialogRef;
  42.                                     var event: EventRecord;
  43.                                     var item: Integer;
  44.                                     yourData: Ptr): Boolean;
  45.     begin
  46.         MySFDialogFilter := CallModalFilterProc(dialog, event, item, GetMyStandardDialogFilter);
  47.     end;  { MySFDialogFilter }
  48.  
  49.     var
  50.  
  51. { static variable for exclusive use by GetMySFDialogFilter }
  52.  
  53.         sMySFDialogFilter: ModalFilterYDUPP;
  54.  
  55.     function GetMySFDialogFilter: ModalFilterYDUpp;
  56.     begin
  57.         if (sMySFDialogFilter = nil) then
  58.             sMySFDialogFilter := NewModalFilterYDProc(@MySFDialogFilter);
  59.         GetMySFDialogFilter := sMySFDialogFilter;
  60.     end;  { GetMySFDialogFilter }
  61.  
  62.     function FindMenuItemText (menu: MenuRef;
  63.                                     stringToFind: Str255): Integer;
  64.         var
  65.             item: Integer;
  66.             itemText: Str255;
  67.     begin
  68.         for item := CountMItems(menu) downto 1 do
  69.             begin
  70.                 GetMenuItemText(menu, item, itemText);
  71.                 if EqualString(itemText, stringToFind, false, false) then
  72.                     Leave;
  73.             end;
  74.         FindMenuItemText := item;
  75.     end;  { FindMenuItemText }
  76.  
  77.     function EqualColor (var rgb1, rgb2: RGBColor): Boolean;
  78.     begin
  79.         EqualColor := (rgb1.red = rgb2.red) and (rgb1.green = rgb2.green) and (rgb1.blue = rgb2.blue);
  80.     end;  { EqualColor }
  81.  
  82.     procedure PrepareMenus;
  83.         var
  84.             window: WindowRef;
  85.             we: WEReference;
  86.             menu: MenuRef;
  87.             item: Integer;
  88.             itemText: Str255;
  89.             selStart, selEnd: LongInt;
  90.             actionKind: WEActionKind;
  91.             mode: Integer;
  92.             ts: TextStyle;
  93.             temp: Boolean;
  94.     begin
  95.  
  96. { get a pointer to the frontmost window, if any }
  97.         window := FrontWindow;
  98.  
  99. { get associated WE instance }
  100.         we := DocumentPeek(window)^.we;
  101.  
  102. { *** FILE MENU *** }
  103.         menu := GetMenuHandle(kMenuFile);
  104.  
  105. { first disable all items }
  106.         for item := CountMItems(menu) downto 1 do
  107.             DisableItem(menu, item);
  108.  
  109. { New, Open and Quit are always enabled }
  110.         EnableItem(menu, kItemNew);
  111.         EnableItem(menu, kItemOpen);
  112.         EnableItem(menu, kItemQuit);
  113.  
  114. { enable Close and Save As if there is an active window }
  115.         if (window <> WindowRef(0)) then
  116.             begin
  117.                 EnableItem(menu, kItemClose);
  118.                 EnableItem(menu, kItemSaveAs);
  119.  
  120. { enable Save if the active window is dirty }
  121.                 if (WEGetModCount(we) > 0) then
  122.                     EnableItem(menu, kItemSave);
  123.             end;
  124.  
  125. { *** EDIT MENU *** }
  126.         menu := GetMenuHandle(kMenuEdit);
  127.  
  128. { first disable all items }
  129.         for item := CountMItems(menu) downto 1 do
  130.             DisableItem(menu, item);
  131.  
  132. { by default, the Undo menu item should read "Can't Undo" }
  133.         GetIndString(itemText, kUndoStringsID, 1);
  134.         SetMenuItemText(menu, kItemUndo, itemText);
  135.  
  136.         if (window <> WindowRef(0)) then
  137.             begin
  138.  
  139. { enable Paste if there's anything pasteable on the Clipboard }
  140.                 if (WECanPaste(we)) then
  141.                     EnableItem(menu, kItemPaste);
  142.  
  143. { enable Undo if anything can be undone }
  144.                 actionKind := WEGetUndoInfo(temp, we);
  145.                 if (actionKind <> weAKNone) then
  146.                     begin
  147.                         EnableItem(menu, kItemUndo);
  148.  
  149. { change the Undo menu item to "Undo"/"Redo" + name of action to undo }
  150.                         GetIndString(itemText, kUndoStringsID, 2 * actionKind + ORD(temp));
  151.                         SetMenuItemText(menu, kItemUndo, itemText);
  152.                     end;
  153.  
  154. { enable Select All if there is anything to select }
  155.                 if (WEGetTextLength(we) > 0) then
  156.                     EnableItem(menu, kItemSelectAll);
  157.  
  158. { get the current selection range }
  159.                 WEGetSelection(selStart, selEnd, we);
  160.                 if (selStart <> selEnd) then
  161.                     begin
  162.  
  163. { enable Cut, Copy and Clear if the selection range is not empty }
  164.                         EnableItem(menu, kItemCut);
  165.                         EnableItem(menu, kItemCopy);
  166.                         EnableItem(menu, kItemClear);
  167.                     end;
  168.  
  169. { determine which style attributes are continuous over the current selection range }
  170. { we'll need this information in order to check the Font/Size/Style/Color menus properly }
  171.                 mode := weDoAll;        { query about all attributes }
  172.                 temp := WEContinuousStyle(mode, ts, we);
  173.             end
  174.         else
  175.             mode := 0;        { no window; so check no item }
  176.  
  177. { *** FONT MENU *** }
  178.         menu := GetMenuHandle(kMenuFont);
  179.  
  180. { first remove all check marks }
  181.         for item := CountMItems(menu) downto 1 do
  182.             CheckItem(menu, item, false);
  183.  
  184. { if there is a continuous font all over the selection range, }
  185. { check the corresponding menu item }
  186.         if (BAND(mode, weDoFont) <> 0) then
  187.             begin
  188.                 GetFontName(ts.tsFont, itemText);
  189.                 CheckItem(menu, FindMenuItemText(menu, itemText), true);
  190.             end;
  191.  
  192. { *** SIZE MENU *** }
  193.         menu := GetMenuHandle(kMenuSize);
  194.  
  195. { first remove all check marks }
  196.         for item := CountMItems(menu) downto 1 do
  197.             CheckItem(menu, item, false);
  198.  
  199. { if there is a continuous font size all over the selection range, }
  200. { check the corresponding menu item }
  201.         if (BAND(mode, weDoSize) <> 0) then
  202.             begin
  203.                 NumToString(ts.tsSize, itemText);
  204.                 CheckItem(menu, FindMenuItemText(menu, itemText), true);
  205.             end;
  206.  
  207. { *** STYLE MENU *** }
  208.         menu := GetMenuHandle(kMenuStyle);
  209.  
  210. { first remove all check marks }
  211.         for item := CountMItems(menu) downto 1 do
  212.             CheckItem(menu, item, false);
  213.  
  214. { check the Style menu items corresponding to style attributes }
  215. { which are continuous over the current selection range }
  216.         if (BAND(mode, weDoFace) <> 0) then
  217.             begin
  218.  
  219.                 if (ts.tsFace = []) then
  220.                     CheckItem(menu, kItemPlainText, true);
  221.  
  222.                 if (bold in ts.tsFace) then
  223.                     CheckItem(menu, kItemBold, true);
  224.  
  225.                 if (italic in ts.tsFace) then
  226.                     CheckItem(menu, kItemItalic, true);
  227.  
  228.                 if (underline in ts.tsFace) then
  229.                     CheckItem(menu, kItemUnderline, true);
  230.  
  231.                 if (outline in ts.tsFace) then
  232.                     CheckItem(menu, kItemOutline, true);
  233.  
  234.                 if (shadow in ts.tsFace) then
  235.                     CheckItem(menu, kItemShadow, true);
  236.  
  237.                 if (condense in ts.tsFace) then
  238.                     CheckItem(menu, kItemCondensed, true);
  239.  
  240.                 if (extend in ts.tsFace) then
  241.                     CheckItem(menu, kItemExtended, true);
  242.  
  243.             end;
  244.  
  245. { *** COLOR MENU *** }
  246.         menu := GetMenuHandle(kMenuColor);
  247.  
  248. { first remove all check marks }
  249.         for item := CountMItems(menu) downto 1 do
  250.             CheckItem(menu, item, false);
  251.  
  252. { if there is a continuous color all over the selection range, }
  253. { check the corresponding menu item (if any) }
  254.         if (BAND(mode, weDoColor) <> 0) then
  255.             with MenuCRsrcHandle(sColors)^^ do
  256.                 for item := numEntries - 1 downto 0 do
  257.                     if (EqualColor(ts.tsColor, mcEntryRecs[item].mctRGB2)) then
  258.                         CheckItem(menu, mcEntryRecs[item].mctItem, true);
  259.  
  260. { *** FEATURES MENU *** }
  261.         menu := GetMenuHandle(kMenuFeatures);
  262.  
  263. { first remove all check marks (except the first item, which has a submenu!!) }
  264.         for item := CountMItems(menu) downto 2 do
  265.             CheckItem(menu, item, false);
  266.  
  267.         if (window <> WindowRef(0)) then
  268.             begin
  269.  
  270. { mark each item according to the corresponding feature }
  271.                 if (WEIsTabHooks(we)) then
  272.                     begin
  273.                         CheckItem(menu, kItemTabHooks, true);
  274.                         DisableItem(menu, kItemAlignment);
  275.                     end
  276.                 else
  277.                     EnableItem(menu, kItemAlignment);
  278.  
  279.                 if Boolean(WEFeatureFlag(weFAutoScroll, weBitTest, we)) then
  280.                     CheckItem(menu, kItemAutoScroll, true);
  281.  
  282.                 if Boolean(WEFeatureFlag(weFOutlineHilite, weBitTest, we)) then
  283.                     CheckItem(menu, kItemOutlineHilite, true);
  284.  
  285.                 if Boolean(WEFeatureFlag(weFReadOnly, weBitTest, we)) then
  286.                     CheckItem(menu, kItemReadOnly, true);
  287.  
  288.                 if Boolean(WEFeatureFlag(weFIntCutAndPaste, weBitTest, we)) then
  289.                     CheckItem(menu, kItemIntCutAndPaste, true);
  290.  
  291.                 if Boolean(WEFeatureFlag(weFDragAndDrop, weBitTest, we)) then
  292.                     CheckItem(menu, kItemDragAndDrop, true);
  293.  
  294.                 if Boolean(WEFeatureFlag(weFDrawOffscreen, weBitTest, we)) then
  295.                     CheckItem(menu, kItemOffscreenDrawing, true);
  296.  
  297.             end;
  298.  
  299. { *** ALIGNMENT MENU *** }
  300.         menu := GetMenuHandle(kMenuAlignment);
  301.  
  302. { first remove all check marks }
  303.         for item := CountMItems(menu) downto 1 do
  304.             CheckItem(menu, item, false);
  305.  
  306.         if (window <> WindowRef(0)) then
  307.             begin
  308.  
  309. { find the Alignment menu item corresponding to the current alignment style }
  310.                 case WEGetAlignment(we) of
  311.  
  312.                     weFlushLeft: 
  313.                         item := kItemAlignLeft;
  314.  
  315.                     weFlushRight: 
  316.                         item := kItemAlignRight;
  317.  
  318.                     weFlushDefault: 
  319.                         item := kItemAlignDefault;
  320.  
  321.                     weCenter: 
  322.                         item := kItemCenter;
  323.  
  324.                     weJustify: 
  325.                         item := kItemJustify;
  326.  
  327.                     otherwise
  328.                         ;
  329.                 end;  { case }
  330.  
  331. { check the menu item }
  332.                 CheckItem(menu, item, true);
  333.             end;
  334.     end;  { PrepareMenus }
  335.  
  336.     procedure DoDeskAcc (menuItem: Integer);
  337.         var
  338.             daName: Str255;
  339.             daNumber: Integer;
  340.     begin
  341.         GetMenuItemText(GetMenuHandle(kMenuApple), menuItem, daName);
  342.         daNumber := OpenDeskAcc(daName);
  343.     end;  { DoDeskAcc }
  344.  
  345.     function DoNew: OSErr;
  346.     begin
  347.  
  348. { create a new window from scratch }
  349.         DoNew := CreateWindow(nil);
  350.     end;  { DoNew }
  351.  
  352.     function DoOpen: OSErr;
  353.         var
  354.             reply: StandardFileReply;
  355.             typeList: SFTypeList;
  356.     begin
  357.         DoOpen := noErr;
  358.  
  359. { set up a list of file types we can open for StandardGetFile }
  360.         typeList[0] := kTypeText;
  361.  
  362. { put up the standard Open dialog box }
  363. { (we use CustomGetFile instead of StandardGetFile because we want to provide }
  364. { our own dialog filter procedure that takes care of updating our windows) }
  365. {$IFC NOT UNDEFINED THINK_PASCAL}
  366.         CustomGetFile(nil, 1, typeList, reply, 0, Point(-1), nil, GetMySFDialogFilter, nil, nil, nil);
  367. {$ELSEC}
  368.         CustomGetFile(nil, 1, @typeList, reply, 0, Point(-1), nil, GetMySFDialogFilter, nil, nil, nil);
  369. {$ENDC}
  370.  
  371.  
  372. { if the user okayed the dialog, create a new window from the specified file }
  373.         if (reply.sfGood) then
  374.             DoOpen := CreateWindow(@reply.sfFile)
  375.         else
  376.             DoOpen := userCanceledErr;
  377.  
  378.     end;  { DoOpen }
  379.  
  380.     function SaveWindow (pFileSpec: FSSpecPtr;
  381.                                     window: WindowRef): OSErr;
  382.         var
  383.             err: OSErr;
  384.     begin
  385.         ForgetHandle(DocumentPeek(window)^.fileAlias);
  386.  
  387. { save the text }
  388.         err := WriteTextFile(pFileSpec, DocumentPeek(window)^.we);
  389.         if (err = noErr) then
  390.             begin
  391.  
  392. { set the window title to the file name }
  393.                 SetWTitle(window, pFileSpec^.name);
  394.  
  395. { replace the old window alias (if any) with a new one created from pFileSpec }
  396.                 ForgetHandle(DocumentPeek(window)^.fileAlias);
  397.                 err := NewAlias(nil, pFileSpec^, AliasHandle(DocumentPeek(window)^.fileAlias));
  398.             end;
  399.  
  400.         SaveWindow := err;
  401.  
  402.     end;  { SaveWindow }
  403.  
  404.     function DoSaveAs (suggestedTarget: FSSpecPtr;
  405.                                     window: WindowRef): OSErr;
  406.         var
  407.             hPrompt: StringHandle;
  408.             defaultName: Str255;
  409.             reply: StandardFileReply;
  410.     begin
  411.  
  412. { get the prompt string for CustomPutFile from a 'STR ' resource and lock it }
  413.         hPrompt := GetString(kPromptStringID);
  414.         HLockHi(Handle(hPrompt));
  415.  
  416. { if a suggested target file is provided, use its name as the default name }
  417.         if (suggestedTarget <> nil) then
  418.             begin
  419.                 defaultName := suggestedTarget^.name;
  420.                 SetDefaultDirectory(suggestedTarget^);
  421.             end
  422.         else
  423.  
  424. { otherwise use the window title as default name for CustomPutFile }
  425.             GetWTitle(window, defaultName);
  426.  
  427. { put up the standard Save dialog box }
  428.         CustomPutFile(hPrompt^^, defaultName, reply, 0, Point(-1), nil, GetMySFDialogFilter, nil, nil, nil);
  429.  
  430. { unlock the string resource }
  431.         HUnlock(Handle(hPrompt));
  432.  
  433. { if the user okayed the dialog, save the window to the specified file }
  434.         if (reply.sfGood) then
  435.             DoSaveAs := SaveWindow(@reply.sfFile, window)
  436.         else
  437.             DoSaveAs := userCanceledErr;
  438.  
  439.     end;  { DoSaveAs }
  440.  
  441.     function DoSave (window: WindowRef): OSErr;
  442.         var
  443.             spec: FSSpec;
  444.             suggestedTarget: FSSpecPtr;
  445.             promptForNewFile, aliasTargetWasChanged: Boolean;
  446.     begin
  447.         suggestedTarget := nil;
  448.         promptForNewFile := true;
  449.  
  450. { resolve the alias associated with this window, if any }
  451.         if (DocumentPeek(window)^.fileAlias <> nil) then
  452.             if (ResolveAlias(nil, AliasHandle(DocumentPeek(window)^.fileAlias), spec, aliasTargetWasChanged) = noErr) then
  453.                 if (aliasTargetWasChanged) then
  454.                     suggestedTarget := @spec
  455.                 else
  456.                     promptForNewFile := false;
  457.  
  458. { if no file has been previously associated with this window, }
  459. { or if the alias resolution has failed, or if the alias target was changed, }
  460. { prompt the user for a new destination }
  461.         if (promptForNewFile) then
  462.             DoSave := DoSaveAs(suggestedTarget, window)
  463.         else
  464.             DoSave := SaveWindow(@spec, window);
  465.  
  466.     end;  { DoSave }
  467.  
  468.     function DoClose (closing: ClosingOption;
  469.                                     saving: SavingOption;
  470.                                     window: WindowRef): OSErr;
  471.         const
  472.             kButtonSave = 1;
  473.             kButtonCancel = 2;
  474.             kButtonDontSave = 3;
  475.         var
  476.             s: Str255;
  477.             alertResult: Integer;
  478.             err: OSErr;
  479.     begin
  480.         DoClose := noErr;
  481.  
  482. { is this window dirty? }
  483.         if (WEGetModCount(DocumentPeek(window)^.we) > 0) then
  484.             begin
  485.  
  486. { do we have to ask the user whether to save changes? }
  487.                 if (saving = savingAsk) then
  488.                     begin
  489.  
  490. { prepare the parametric strings to be used in the Save Changes alert box }
  491.                         GetWTitle(window, s);
  492.                         ParamText(s, StringPtr(nil)^, StringPtr(nil)^, StringPtr(nil)^);
  493.                         GetIndString(s, kClosingQuittingStringsID, 1 + ORD(closing));
  494.                         ParamText(StringPtr(nil)^, s, StringPtr(nil)^, StringPtr(nil)^);
  495.  
  496. { put up the Save Changes? alert box }
  497. {$IFC NOT UNDEFINED THINK_PASCAL}
  498.                         SetCursor(arrow);
  499. {$ELSEC}
  500.                         SetCursor(qd.arrow);
  501. {$ENDC}
  502.                         alertResult := Alert(kAlertSaveChanges, GetMyStandardDialogFilter);
  503.  
  504. { exit if the user canceled the alert box }
  505.                         if (alertResult = kButtonCancel) then
  506.                             begin
  507.                                 DoClose := userCanceledErr;
  508.                                 Exit(DoClose);
  509.                             end;
  510.  
  511.                         if (alertResult = kButtonSave) then
  512.                             saving := savingYes
  513.                         else
  514.                             saving := savingNo;
  515.                     end;  { if saving = savingAsk }
  516.  
  517.                 if (saving = savingYes) then
  518.                     begin
  519.                         err := DoSave(window);
  520.                         if (err <> noErr) then
  521.                             begin
  522.                                 DoClose := err;
  523.                                 Exit(DoClose);
  524.                             end;
  525.                     end;
  526.             end;  { if window is dirty }
  527.  
  528. { destroy the window }
  529.         DestroyWindow(window);
  530.  
  531.     end;  { DoClose }
  532.  
  533.     function DoQuit (saving: SavingOption): OSErr;
  534.         var
  535.             window: WindowRef;
  536.             err: OSErr;
  537.     begin
  538.         DoQuit := noErr;
  539.  
  540. { close all open windows }
  541.         repeat
  542.             window := FrontWindow;
  543.             if (window <> WindowRef(0)) then
  544.                 begin
  545.                     err := DoClose(closingApplication, saving, window);
  546.                     if (err <> noErr) then
  547.                         begin
  548.                             DoQuit := err;
  549.                             Exit(DoQuit);
  550.                         end;
  551.                 end;
  552.         until (window = WindowRef(0));
  553.  
  554. { set a flag so we drop out of the event loop }
  555.         gExiting := true;
  556.  
  557.     end;  { DoQuit }
  558.  
  559.     procedure DoAppleChoice (menuItem: Integer);
  560.     begin
  561.         if (menuItem = kItemAbout) then
  562.             DoAboutBox(kDialogAboutBox)
  563.         else
  564.             DoDeskAcc(menuItem);
  565.     end;  { DoAppleChoice }
  566.  
  567.     procedure DoFileChoice (menuItem: Integer);
  568.         var
  569.             window: WindowRef;
  570.     begin
  571.         window := FrontWindow;
  572.  
  573.         case menuItem of
  574.  
  575.             kItemNew: 
  576.                 if (DoNew <> noErr) then
  577.                     ;
  578.  
  579.             kItemOpen: 
  580.                 if (DoOpen <> noErr) then
  581.                     ;
  582.  
  583.             kItemClose: 
  584.                 if (DoClose(closingWindow, savingAsk, window) <> noErr) then
  585.                     ;
  586.  
  587.             kItemSave: 
  588.                 if (DoSave(window) <> noErr) then
  589.                     ;
  590.  
  591.             kItemSaveAs:
  592.                 if (DoSaveAs(FSSpecPtr(0), window) <> noErr) then
  593.                     ;
  594.  
  595.             kItemQuit: 
  596.                 if (DoQuit(savingAsk) <> noErr) then
  597.                     ;
  598.  
  599.             otherwise
  600.                 ;
  601.         end;  { case menuItem }
  602.     end;  { DoFileChoice }
  603.  
  604.     procedure DoEditChoice (menuItem: Integer);
  605.         var
  606.             window: WindowRef;
  607.             we: WEReference;
  608.     begin
  609.  
  610. { do nothing if no window is active }
  611.         window := FrontWindow;
  612.         if (window = WindowRef(0)) then
  613.             Exit(DoEditChoice);
  614.         we := DocumentPeek(window)^.we;
  615.  
  616.         case menuItem of
  617.  
  618.             kItemUndo: 
  619.                 if (WEUndo(we) <> noErr) then
  620.                     ;
  621.  
  622.             kItemCut: 
  623.                 if (WECut(we) <> noErr) then
  624.                     ;
  625.  
  626.             kItemCopy: 
  627.                 if (WECopy(we) <> noErr) then
  628.                     ;
  629.  
  630.             kItemPaste: 
  631.                 if (WEPaste(we) <> noErr) then
  632.                     ;
  633.  
  634.             kItemClear: 
  635.                 if (WEDelete(we) <> noErr) then
  636.                     ;
  637.  
  638.             kItemSelectAll: 
  639.                 WESetSelection(0, maxLongInt, we);
  640.  
  641.             otherwise
  642.                 ;
  643.         end;  { case }
  644.     end;  { DoEditChoice }
  645.  
  646.     procedure DoFontChoice (menuItem: Integer);
  647.         var
  648.             window: WindowRef;
  649.             fontName: Str255;
  650.             ts: TextStyle;
  651.     begin
  652.         window := FrontWindow;
  653.         if (window <> WindowRef(0)) then
  654.             begin
  655.                 GetMenuItemText(GetMenuHandle(kMenuFont), menuItem, fontName);
  656.                 GetFNum(fontName, ts.tsFont);
  657.                 if (WESetStyle(weDoFont, ts, DocumentPeek(window)^.we) <> noErr) then
  658.                     ;
  659.             end;
  660.     end;  { DoFontChoice }
  661.  
  662.     procedure DoSizeChoice (menuItem: Integer);
  663.         var
  664.             window: WindowRef;
  665.             sizeString: Str255;
  666.             longSize: LongInt;
  667.             mode: Integer;
  668.             ts: TextStyle;
  669.     begin
  670.         window := FrontWindow;
  671.         if (window <> WindowRef(0)) then
  672.             begin
  673.  
  674.                 if (menuItem <= kItemLastSize) then
  675.                     begin
  676.                         GetMenuItemText(GetMenuHandle(kMenuSize), menuItem, sizeString);
  677.                         StringToNum(sizeString, longSize);
  678.                         mode := weDoSize;
  679.                         ts.tsSize := longSize;
  680.                     end
  681.                 else if (menuItem = kItemSmaller) then
  682.                     begin
  683.                         mode := weDoAddSize;
  684.                         ts.tsSize := -1;
  685.                     end
  686.                 else if (menuItem = kItemLarger) then
  687.                     begin
  688.                         mode := weDoAddSize;
  689.                         ts.tsSize := +1;
  690.                     end;
  691.  
  692.                 if (WESetStyle(mode, ts, DocumentPeek(window)^.we) <> noErr) then
  693.                     ;
  694.  
  695.             end;
  696.     end;  { DoSizeChoice }
  697.  
  698.     procedure DoStyleChoice (menuItem: Integer);
  699.         var
  700.             window: WindowRef;
  701.             ts: TextStyle;
  702.     begin
  703.         window := FrontWindow;
  704.         if (window <> WindowRef(0)) then
  705.             begin
  706.  
  707.                 case menuItem of
  708.  
  709.                     kItemPlainText: 
  710.                         ts.tsFace := [];
  711.  
  712.                     kItemBold: 
  713.                         ts.tsFace := [bold];
  714.  
  715.                     kItemItalic: 
  716.                         ts.tsFace := [italic];
  717.  
  718.                     kItemUnderline: 
  719.                         ts.tsFace := [underline];
  720.  
  721.                     kItemOutline: 
  722.                         ts.tsFace := [outline];
  723.  
  724.                     kItemShadow: 
  725.                         ts.tsFace := [shadow];
  726.  
  727.                     kItemCondensed: 
  728.                         ts.tsFace := [condense];
  729.  
  730.                     kItemExtended: 
  731.                         ts.tsFace := [extend];
  732.  
  733.                     otherwise
  734.                         Exit(DoStyleChoice);
  735.                 end;  { case menuItem }
  736.  
  737.                 if (WESetStyle(weDoFace + weDoToggleFace, ts, DocumentPeek(window)^.we) <> noErr) then
  738.                     ;
  739.  
  740.             end;
  741.     end;  { DoStyleChoice }
  742.  
  743.     procedure DoColorChoice (menuItem: Integer);
  744.         var
  745.             window: WindowRef;
  746.             i: Integer;
  747.             ts: TextStyle;
  748.     begin
  749.  
  750. { do nothing if there is no front window }
  751.         window := FrontWindow;
  752.         if (window = WindowRef(0)) then
  753.             Exit(DoColorChoice);
  754.  
  755. { find the color corresponding to the chosen menu item }
  756.         with MenuCRsrcHandle(sColors)^^ do
  757.             for i := numEntries - 1 downto 0 do
  758.                 if (mcEntryRecs[i].mctItem = menuItem) then
  759.                     begin
  760.                         ts.tsColor := mcEntryRecs[i].mctRGB2;
  761.                         if (WESetStyle(weDoColor, ts, DocumentPeek(window)^.we) <> noErr) then
  762.                             ;
  763.                     end;
  764.     end;  { DoColorChoice }
  765.  
  766.     procedure DoAlignChoice (menuItem: Integer);
  767.         var
  768.             window: WindowRef;
  769.             alignment: SignedByte;
  770.     begin
  771.         window := FrontWindow;
  772.         if (window <> WindowRef(0)) then
  773.             begin
  774.  
  775.                 case menuItem of
  776.  
  777.                     kItemAlignDefault: 
  778.                         alignment := weFlushDefault;
  779.  
  780.                     kItemAlignLeft: 
  781.                         alignment := weFlushLeft;
  782.  
  783.                     kItemCenter: 
  784.                         alignment := weCenter;
  785.  
  786.                     kItemAlignRight: 
  787.                         alignment := weFlushRight;
  788.  
  789.                     kItemJustify: 
  790.                         alignment := weJustify;
  791.  
  792.                     otherwise
  793.                         Exit(DoAlignChoice);
  794.                 end;  { case }
  795.  
  796. { set the alignment mode (this automatically redraws the text) }
  797.                 WESetAlignment(alignment, DocumentPeek(window)^.we);
  798.  
  799.             end;
  800.     end;  { DoAlignChoice }
  801.  
  802.     procedure DoFeatureChoice (menuItem: Integer);
  803.         var
  804.             window: WindowRef;
  805.             we: WEReference;
  806.             feature, oldSetting: Integer;
  807.     begin
  808.         window := FrontWindow;
  809.         if (window = WindowRef(0)) then
  810.             Exit(DoFeatureChoice);
  811.         we := DocumentPeek(window)^.we;
  812.  
  813.         if (menuItem = kItemTabHooks) then
  814.             begin
  815.  
  816. { install or remove our custom tab hooks }
  817.                 if (WEIsTabHooks(we) = false) then
  818.                     begin
  819.  
  820. { left-align the text (the hooks only work with left-aligned text) }
  821.                         WESetAlignment(weFlushLeft, we);
  822.  
  823. { install tab hooks }
  824.                         if (WEInstallTabHooks(we) <> noErr) then
  825.                             ;
  826.  
  827.                     end
  828.                 else
  829.                     begin
  830.  
  831. { remove tab hooks }
  832.                         if (WERemoveTabHooks(we) <> noErr) then
  833.                             ;
  834.                     end;
  835.  
  836. { turn the cursor into a wristwatch }
  837.                 SetCursor(GetCursor(watchCursor)^^);
  838.  
  839. { recalculate line breaks and redraw the text }
  840.                 if (WECalText(we) <> noErr) then
  841.                     ;
  842.             end
  843.         else
  844.             begin
  845.                 case menuItem of
  846.  
  847.                     kItemAutoScroll: 
  848.                         feature := weFAutoScroll;
  849.  
  850.                     kItemOutlineHilite: 
  851.                         feature := weFOutlineHilite;
  852.  
  853.                     kItemReadOnly: 
  854.                         feature := weFReadOnly;
  855.  
  856.                     kItemIntCutAndPaste: 
  857.                         feature := weFIntCutAndPaste;
  858.  
  859.                     kItemDragAndDrop: 
  860.                         feature := weFDragAndDrop;
  861.  
  862.                     kItemOffscreenDrawing: 
  863.                         feature := weFDrawOffscreen;
  864.  
  865.                     otherwise
  866.                         ;
  867.                 end;  { case }
  868.  
  869. { toggle the specified feature }
  870.                 oldSetting := WEFeatureFlag(feature, weBitToggle, we);
  871.  
  872.             end;
  873.     end;  { DoFeatureChoice }
  874.  
  875.     procedure DoMenuChoice (menuChoice: LongInt);
  876.         var
  877.             menuID, menuItem: Integer;
  878.     begin
  879.  
  880. { extract menu ID and menu item from menuChoice }
  881.         menuID := HiWrd(menuChoice);
  882.         menuItem := LoWrd(menuChoice);
  883.  
  884. { dispatch on menuID }
  885.         case menuID of
  886.  
  887.             kMenuApple: 
  888.                 DoAppleChoice(menuItem);
  889.  
  890.             kMenuFile: 
  891.                 DoFileChoice(menuItem);
  892.  
  893.             kMenuEdit: 
  894.                 DoEditChoice(menuItem);
  895.  
  896.             kMenuFont: 
  897.                 DoFontChoice(menuItem);
  898.  
  899.             kMenuSize: 
  900.                 DoSizeChoice(menuItem);
  901.  
  902.             kMenuStyle: 
  903.                 DoStyleChoice(menuItem);
  904.  
  905.             kMenuColor: 
  906.                 DoColorChoice(menuItem);
  907.  
  908.             kMenuFeatures: 
  909.                 DoFeatureChoice(menuItem);
  910.  
  911.             kMenuAlignment: 
  912.                 DoAlignChoice(menuItem);
  913.  
  914.             otherwise
  915.                 ;
  916.         end;  { case menuID }
  917.  
  918.         HiliteMenu(0);
  919.  
  920.     end;  { DoMenuChoice }
  921.  
  922. {$S Init}
  923.  
  924.     function InitializeMenus: OSErr;
  925.         var
  926.             err: OSErr;
  927.     begin
  928.         InitializeMenus := noErr;
  929.  
  930. { build up the whole menu bar from the 'MBAR' resource }
  931.         SetMenuBar(GetNewMBar(kMenuBarID));
  932.  
  933. { add names to the Apple and Font menus }
  934.         AppendResMenu(GetMenuHandle(kMenuApple), kTypeDeskAccessory);
  935.         AppendResMenu(GetMenuHandle(kMenuFont), kTypeFont);
  936.  
  937. { insert the Alignment submenu into the hierarchical portion of the menu list }
  938.         InsertMenu(GetMenu(kMenuAlignment), -1);
  939.  
  940. { disable the "Drag and Drop Editing" item in the Features menu once and for all }
  941. { if the Drag Manager isn't available }
  942.         if (gHasDragAndDrop = false) then
  943.             DisableItem(GetMenuHandle(kMenuFeatures), kItemDragAndDrop);
  944.  
  945. { load the menu color table for the Color menu }
  946.         sColors := GetResource(kTypeMenuColorTable, kMenuColor);
  947.         err := ResError;
  948.         if (err <> noErr) then
  949.             begin
  950.                 InitializeMenus := err;
  951.                 Exit(InitializeMenus);
  952.             end;
  953.         HNoPurge(sColors);
  954.  
  955. { draw the menu bar }
  956.         DrawMenuBar;
  957.  
  958.     end;  { InitializeMenus }
  959.  
  960. end.